package wml.clipstore.storage.clips;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.util.List;

import CLIPSJNI.Environment;
import CLIPSJNI.InstanceAddressValue;

import test.beans.User;
import wml.clipstore.base.Entity;
import wml.clipstore.base.FieldValue;
import wml.clipstore.base.RawEntity;
import wml.clipstore.map.MapManager;
import wml.clipstore.restriction.Restriction;

public class ClipsStorage {

	private Environment clips = new Environment();

	private Manipulater maner = new Manipulater(clips);
	private ClipsSaver saver = new ClipsSaver(clips);
	private ClipsGetter getter = new ClipsGetter(clips);

	public static void main(String args[]) {
		ClipsStorage clips = new ClipsStorage();
		User user = new User();
		user.setAge(21);
		user.setGender("男");
		user.setName("WangMingliang");
		clips.persist();
		User u = null;
		u = clips.getByField(User.class, new Restriction("name", "eq",
				"WangMingliang"));
		System.out.println(u.getGender());
		clips.close();
	}

	public void close() {
		this.clips.clear();
		this.clips.destroy();
	}

	public ClipsStorage() {
		init();
	}

	public ClipsStorage(String data) {
		init(data);
	}

	private void init() {
		try {
			File file = this.getConstructFile();
			clips.load(file.getAbsolutePath());
			file.delete();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private void init(String data) {
		this.init();
		clips.eval("(load-instances " + data + ")");
		clips.run();
	}

	private File getConstructFile() throws IOException {
		File file = File.createTempFile("init", ".clp");
		FileWriter w = new FileWriter(file);
		List<String> classes = MapManager.getInstance().getClasses();
		List<String> rules = MapManager.getInstance().getRules();
		for (String t : classes) {
			w.write(t);
			w.flush();
		}
		for (String t : rules) {
			w.write(t);
			w.flush();
		}
		w.close();
		return file;
	}

	public void persist() {
		clips.eval("(save C://clips/init.clp)");
		clips.eval("(save-instances C://clips/instances.clp)");
	}

	public void saveEntity(Entity entity) {
		this.saver.save(entity);
	}

	public <T extends Entity> RawEntity getRawByField(Class<T> clazz,
			Restriction restriction) {
		InstanceAddressValue iav = this.getter.getInstance(clazz.getName(),
				restriction.toString());
		if (iav != null) {
			try {
				Constructor<RawEntity> c = RawEntity.class
						.getDeclaredConstructor(InstanceAddressValue.class);
				c.setAccessible(true);
				return c.newInstance(iav);
			} catch (Exception e) {
				e.printStackTrace();
				return null;
			}
		}
		return null;
	}

	public <T extends Entity> T getByField(Class<T> clazz,
			Restriction restriction) {
		InstanceAddressValue iav = this.getter.getInstance(clazz.getName(),
				restriction.toString());
		if (iav != null) {
			try {
				return this.getter.getEntity(iav, clazz);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return null;
	}

	public boolean delete(Class<? extends Entity> clazz, Restriction restriction) {
		return this.maner.delete(clazz.getName(), restriction.toString());
	}

	public boolean update(Class<? extends Entity> clazz,
			Restriction restriction, List<FieldValue> values) {
		return this.maner.update(clazz.getName(), restriction.toString(),
				values);
	}
}